using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using XUCore.Ddd.Domain;
using XUCore.NetCore.FreeSql.Entity;

namespace XUCore.NetCore.FreeSql.Curd
{
    /// <summary>
    /// Curd操作类
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TUKey"></typeparam>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TUser"></typeparam>
    public class CurdEntity<TKey, TUKey, TEntity, TUser> : CurdEntity<TKey, TEntity>
        where TEntity : class, IEntity<TKey>, new()
        where TUser : class, IUser
    {
        public readonly TUser User;
        /// <summary>
        /// 主键为string的Curd操作类
        /// </summary>
        /// <param name="db"></param>
        /// <param name="mapper"></param>
        /// <param name="user"></param>
        public CurdEntity(FreeSqlUnitOfWorkManager db, IMapper mapper, TUser user)
            : this(db.Orm, mapper, user)
        {
        }
        /// <summary>
        /// 主键为string的Curd操作类
        /// </summary>
        /// <param name="freeSql"></param>
        /// <param name="mapper"></param>
        /// <param name="user"></param>
        public CurdEntity(IFreeSql freeSql, IMapper mapper, TUser user)
            : base(freeSql, mapper)
        {
            this.User = user;
        }
        /// <summary>
        /// 设置更新的列<para></para>
        ///     注意：标记 [Column(CanUpdate = false)] 的属性不会被更新<para></para>
        /// </summary>
        /// <param name="exp"></param>
        /// <param name="keyValues">var keyValues = new Dictionary&lt;string, object&gt;{ { "field1", 1 } , { "field2", "test" } };</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task<int> UpdateFieldAsync(Expression<Func<TEntity, bool>> exp, Dictionary<string, object> keyValues, CancellationToken cancellationToken = default)
        {
            if (ContainProperty(nameof(EntityFull<TKey, TUKey>.ModifiedAt)) && !keyValues.ContainsKey(nameof(EntityFull<TKey, TUKey>.ModifiedAt)))
                keyValues.Add(nameof(EntityFull<TKey, TUKey>.ModifiedAt), DateTime.Now);

            if (ContainProperty(nameof(EntityFull<TKey, TUKey>.ModifiedAtUserId)) && !keyValues.ContainsKey(nameof(EntityFull<TKey, TUKey>.ModifiedAtUserId)))
                keyValues.Add(nameof(EntityFull<TKey, TUKey>.ModifiedAtUserId), User.GetId<TUKey>());

            if (ContainProperty(nameof(EntityFull<TKey, TUKey>.ModifiedAtUserName)) && !keyValues.ContainsKey(nameof(EntityFull<TKey, TUKey>.ModifiedAtUserName)))
                keyValues.Add(nameof(EntityFull<TKey, TUKey>.ModifiedAtUserName), User.Name);

            return await base.UpdateFieldAsync(exp, keyValues, cancellationToken);
        }
    }
}